package com.dkts.oil.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dkts.oil.converter.GeometryConverter;
import com.dkts.oil.mysql.entity.OilObstacle;
import com.dkts.oil.repository.OilImportRepositoryImpl;
import com.dkts.oil.util.FileToStringUtils;
import com.dkts.oil.util.GeoAreaUtil;
import com.dkts.oil.util.GeoOutUtil;
import com.dkts.oil.util.gis.HexUtil;
import com.dkts.oil.web.vo.request.OilImportRequest;
import com.dkts.oil.web.vo.request.OilWatermportRequest;
import com.dkts.oil.web.vo.request.OilWayImportRequest;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author heguanglong
 * @since 2025-01-07
 */
@Service
@Slf4j
public class OilImportInfoServiceImpl {


    @Autowired
    private OilImportRepositoryImpl poiImportRepository;

    public Boolean importInfo(OilImportRequest request) throws Exception {
        String data = FileToStringUtils.txt2String(new File(request.getUrl()));
        JSONArray jsonArray = JSONObject.parseObject(data).getJSONArray("features");
        int row = jsonArray.size();
        List<OilObstacle> list = new ArrayList<>(3000);
        for (int i = 0; i < row; i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            JSONObject properties = jsonObject.getJSONObject("properties");
            JSONObject geometry = jsonObject.getJSONObject("geometry");
            insertDbBatch(list,properties, geometry, request);
        }
        if (list.size() > 0) {
            poiImportRepository.batchImportPoi(list);
        }
        return true;
    }

    private void insertDbBatch(List<OilObstacle> list, JSONObject properties, JSONObject geometry, OilImportRequest request) throws Exception {
        Geometry geometryA = GeoOutUtil.dataDrawGeometryALL(geometry);
        String name= properties.getString("NAME");
        Integer _label = properties.getInteger("_label");
        properties.remove("NAME");
        properties.remove("path");
        properties.remove("_label");
        properties.remove("layer");

        Point point = geometryA.getCentroid();
        double [] area =GeoAreaUtil.calculateAreaInSquareMeters(geometryA);
        list.add(new OilObstacle(name, _label, geometryA.toText(), HexUtil.geoToH3Address(point.getX(), point.getY(), 6),
                JSONObject.toJSONString(properties), geometryA.getCentroid(), area[1],area[0]));
        try {
            synchronized (list) {
                if (list.size() > request.getRow()) {
                    int rowInsert = poiImportRepository.batchImportPoi(list);
                    list.clear();
                    log.info("rowInsert:{}", rowInsert);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void insertDbBatch(List<OilObstacle> list, JSONObject properties,  Geometry geometryA, OilImportRequest request) throws Exception {
        Point point = geometryA.getCentroid();
        String name= properties.getString("name");
        Integer _label = properties.getInteger("_label");
        properties.remove("name");
        properties.remove("path");
        properties.remove("_label");
        properties.remove("layer");
        double [] area =GeoAreaUtil.calculateAreaInSquareMeters(geometryA);
        list.add(new OilObstacle(name, _label, geometryA.toText(), HexUtil.geoToH3Address(point.getX(), point.getY(), 6), JSONObject.toJSONString(properties), geometryA.getCentroid(),area[1],area[0]));
        try {
            synchronized (list) {
                if (list.size() > request.getRow()) {
                    int rowInsert = poiImportRepository.batchImportPoi(list);
                    list.clear();
                    log.info("rowInsert:{}", rowInsert);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Boolean importInfoBuild(OilImportRequest request) throws Exception {
        try (BufferedReader br = new BufferedReader(new FileReader(request.getUrl()))) {
            String line;
            List<OilObstacle> list = new ArrayList<>(3000);
            while ((line = br.readLine()) != null) {
                try {
                    JSONObject jsonObject = JSONObject.parseObject(line);
                    JSONObject geometry = jsonObject.getJSONObject("geometry");
                    JSONObject properties = jsonObject.getJSONObject("properties");
                    properties.remove("path");
                    properties.remove("name");
                    properties.put("_label", "-100");
                    String json= geometry.toJSONString();
                    Geometry geometry1=GeometryConverter.geoJsonToGeometry(json);
                    insertDbBatch(list, properties, geometry1, request);
                } catch (Exception e) {
                    log.error(line);
                    e.printStackTrace();
                }
            }
            if (list.size() > 0) {
                poiImportRepository.batchImportPoi(list);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }
    private void insertDbBatchRoad(List<OilObstacle> list, JSONObject properties,  Geometry geometryA, OilImportRequest request) throws Exception {
        Point point = geometryA.getCentroid();
        Integer _label = properties.getInteger("_label");
        String name= properties.getString("name");
        properties.remove("_label");
        properties.remove("name");
        properties.remove("_label");
        properties.remove("name");
        properties.remove("maxspeed");
        properties.remove("bridge");
        properties.remove("tunnel");
        properties.remove("type");
        properties.remove("oneway");
        properties.remove("fclass");
        properties.remove("code");
        properties.remove("osm_id");
        properties.remove("ID");
        properties.remove("OBJECTID");
        properties.remove("REMARK");
        properties.remove("Shape_Leng");
        properties.remove("Shape_Area");
        double [] area =GeoAreaUtil.calculateAreaInSquareMeters(geometryA);
        list.add(new OilObstacle(name, _label, geometryA.toText(), HexUtil.geoToH3Address(point.getX(), point.getY(), 6), JSONObject.toJSONString(properties), geometryA.getCentroid(),area[1],area[0]));
        try {
            synchronized (list) {
                if (list.size() > request.getRow()) {
                    int rowInsert = poiImportRepository.batchImportPoi(list);
                    list.clear();
                    log.info("rowInsert:{}", rowInsert);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public Boolean importInfoRoad(OilImportRequest request,Integer label) {
        try (BufferedReader br = new BufferedReader(new FileReader(request.getUrl()))) {
            String line;
            List<OilObstacle> list = new ArrayList<>(3000);
            while ((line = br.readLine()) != null) {
                try {
                    JSONObject jsonObject = JSONObject.parseObject(line);
                    JSONObject geometry = jsonObject.getJSONObject("geometry");
                    JSONObject properties = jsonObject.getJSONObject("properties");
                    properties.remove("path");
                    properties.put("_label", label);
                    double buffer=10;
                    properties.remove("layer");
                    String json= geometry.toJSONString();
                    Geometry geometry1=GeometryConverter.geoJsonToGeometry(json);
                    Geometry geometry2= GeometryConverter.getBuff(geometry1,buffer);
//                    Geometry gcj02To84=GeometryConverter.transformGCJ02ToWGS84(geometry2);
                    insertDbBatchRoad(list, properties, geometry2, request);
                } catch (Exception e) {
                    log.error(line);
                    e.printStackTrace();
                }
            }
            if (list.size() > 0) {
                poiImportRepository.batchImportPoi(list);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    public boolean wayRoad(OilWayImportRequest request) {
        OilImportRequest bean = new OilImportRequest();
        BeanUtils.copyProperties(request, bean);
        return this.importInfoRoad(bean, -104);
    }

    public boolean water(OilWatermportRequest request) {
        OilImportRequest bean = new OilImportRequest();
        BeanUtils.copyProperties(request, bean);
        return this.importInfoRoad(bean, -103);
    }
}
